﻿#include<iostream>

#include<BRepPrimAPI_MakeBox.hxx>

#include<IVtkTools_ShapeDataSource.hxx>
#include<IVtkTools_ShapePicker.hxx>
#include<IVtk_IShapeMesher.hxx>
#include<IVtkOCC_ShapeMesher.hxx>

#include<vtkCommand.h>
#include<vtkTextProperty.h>
#include<vtkCallbackCommand.h>
#include<vtkImageData.h> 
#include<vtkHardwareSelector.h>
#include<vtkSelectionNode.h>
#include<vtkProperty.h>
#include<vtkProp3DCollection.h>
#include<vtkAutoInit.h>
#include<vtkWindowToImageFilter.h>
#include<vtkSmartPointer.h>

#include "VTKRenderer.h"

using namespace std;

vtkStandardNewMacro(CustomInteractorStyle);
void CustomInteractorStyle::SetRenderer(VTKRenderer *renderer)
{
    m_Renderer = renderer;
}

void CustomInteractorStyle::OnLeftButtonDown()
{    
    if (Interactor->GetShiftKey()) 
    {
        // Shift+左键：开始旋转
        m_IsRotating = true;
        StartRotate();
    }
    else 
    {
        // 普通左键：记录起始位置， 此时有可能是单选有可能是框选，用于框选
        m_IsSelecting = true;
        m_IsMouseMoveing = false;
        Interactor->GetEventPosition(m_StartPos);
    }
    vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
}

void CustomInteractorStyle::OnLeftButtonUp()
{    
    if (m_IsRotating) 
    {
        // 结束旋转
        EndRotate();
        m_IsRotating = false;
    }
    else if (m_IsSelecting) 
    {
        // 触发选择        
        if(!m_IsMouseMoveing)
        {
            // 单选
            if (m_Renderer) m_Renderer->HandleSingleSelection(m_StartPos[0], m_StartPos[1]);
        }
        else
        {
            // 框选
            int pos2[2];
            this->Interactor->GetEventPosition(pos2);
            if (m_Renderer) m_Renderer->HandleBoxSelection(m_StartPos, pos2);
            m_IsMouseMoveing = false;
        }        
        m_IsSelecting = false;
    }
    else
    {
        // nothing
    }
    vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
}

void CustomInteractorStyle::OnMiddleButtonDown()
{
    // 开始平移
    m_IsPanning = true;
    StartPan();
    vtkInteractorStyleTrackballCamera::OnMiddleButtonDown();
}

void CustomInteractorStyle::OnMiddleButtonUp()
{
    // 结束平移
    m_IsPanning = false;
    EndPan();
    vtkInteractorStyleTrackballCamera::OnMiddleButtonUp();
}

void CustomInteractorStyle::OnMouseMove()
{
    if (m_IsRotating)
    {
        Rotate();
    }
    else if (m_IsPanning)
    {
        Pan();
    }
    else if(m_IsSelecting)
    {
        m_IsMouseMoveing = true;
    }
    else
    {
        vtkInteractorStyleTrackballCamera::OnMouseMove();
    }
}

///////////////////////////////////////////////////////////////////////
VTK_MODULE_INIT(vtkRenderingOpenGL2); // 注册渲染器模块
VTK_MODULE_INIT(vtkInteractionStyle); // 注册交互器样式 
VTK_MODULE_INIT(vtkRenderingFreeType);// 注册字体渲染模块
VTKRenderer &VTKRenderer::getInstance()
{    
    static VTKRenderer instance;
    return instance;
}

void VTKRenderer::Initialize()
{
	// 初始化窗口和交互器
	m_RenderWindow->AddRenderer(m_Renderer);
	m_Interactor->SetRenderWindow(m_RenderWindow);    
    m_InteractorStyle->SetRenderer(this);  // 关联自定义交互样式
	m_Interactor->SetInteractorStyle(m_InteractorStyle);
    
	// 添加坐标文本
	vtkNew<vtkTextActor> textActor;
	textActor->SetPosition(10, 10);
	textActor->GetTextProperty()->SetColor(1, 1, 1);
	m_Renderer->AddActor(textActor);
    
    // 初始化鼠标位置文本
    m_MousePositionText->SetPosition(10, 50);
    m_MousePositionText->GetTextProperty()->SetColor(1,1,1);
    m_MousePositionText->GetTextProperty()->SetFontSize(15);
    m_Renderer->AddActor(m_MousePositionText);
    
    // 注册鼠标移动回调
    InitialMouseEvent();

    // 注册渲染回调
    m_RenderCallback->SetCallback([](vtkObject* caller, unsigned long eid, void* clientdata, void* calldata) 
    {
        auto self = static_cast<VTKRenderer*>(clientdata);
        self->UpdateModel();
        self->m_RenderWindow->Render();
    });
    m_RenderCallback->SetClientData(this);
    m_Interactor->AddObserver(vtkCommand::UserEvent, m_RenderCallback);
    
    // 创建切换按钮
	CreateSwitchAPIButton();
}

void VTKRenderer::Rendering(bool high_API)
{
    if(!m_shape.IsNull())
    {
        m_UseHighAPI = high_API;
        
        // 强制在主线程更新并渲染
        m_Interactor->InvokeEvent(vtkCommand::UserEvent); 
        // m_Interactor->InvokeEvent(vtkCommand::UserEvent, [this]() 
        // {
        //     UpdateModel();
        //     m_RenderWindow->Render();
        // });
    }

    if(!m_Isrendering) 
    {
        m_Interactor->Start();
        m_Isrendering = true;
    }
}

void VTKRenderer::SwitchRenderAPI()
{
	m_UseHighAPI = !m_UseHighAPI;
    m_ButtonRep->SetState(m_UseHighAPI ? 0 : 1);
    
	// 如果当前模型已存在，重新渲染
    if (m_CurrentActor) UpdateModel();	
}

void VTKRenderer::ClearAllModels()
{
    // 移除当前Actor
    if (m_CurrentActor) 
    {
        m_Renderer->RemoveActor(m_CurrentActor);
        m_CurrentActor.Reset();
    }

    // 重置模型数据
    m_shape.Nullify();

    // 清除高亮状态
    ClearHighLightState();

    // 强制在主线程渲染
    m_Interactor->InvokeEvent(vtkCommand::UserEvent);
}

void VTKRenderer::AddModel(TopoDS_Shape shape)
{
    m_shape = shape;
}

void VTKRenderer::RemoveModel()
{
    m_shape = TopoDS_Shape();
}

void VTKRenderer::HandleSingleSelection(int x, int y)
{
    m_CellPicker->Pick(x, y, 0, m_Renderer);
    
    // 取消之前的高亮
    ClearHighLightState();    

    // 获取新选择的Actor
    vtkActor* selectedActor = m_CellPicker->GetActor();
    if (selectedActor)
    {
        selectedActor->GetProperty()->SetColor(1,0,0); // 红色高亮
        m_HighlightedActor->ShallowCopy(selectedActor);
    }
    
    m_RenderWindow->Render();
}

void VTKRenderer::HandleBoxSelection(int* pos1, int* pos2)
{
    // 清除之前的高亮
    ClearHighLightState();

    // 执行区域选择
    m_AreaPicker->AreaPick(pos1[0], pos1[1], pos2[0], pos2[1], m_Renderer);
    
    // 获取选中对象
    vtkProp3DCollection* props = m_AreaPicker->GetProp3Ds();
    props->InitTraversal();
    while (vtkProp3D* prop = props->GetNextProp3D()) 
    {
        if (auto actor = vtkActor::SafeDownCast(prop))
        {
            actor->GetProperty()->SetColor(0,1,0);
            m_SelectedActors.push_back(actor);
        }
    }    
    m_RenderWindow->Render();
}

VTKRenderer::VTKRenderer()
{        
	Initialize();
}

VTKRenderer::~VTKRenderer()
{
	m_RenderWindow->Finalize();
}

void VTKRenderer::UpdateModel()
{
	// 清除旧模型
    if (m_CurrentActor) 
    {
        m_Renderer->RemoveActor(m_CurrentActor);
    }

    if (m_UseHighAPI) 
    {
        // 使用高API模式
        vtkNew<IVtkTools_ShapeDataSource> occSource;
        occSource->SetShape(new IVtkOCC_Shape(m_shape));
        m_CurrentMapper->SetInputConnection(occSource->GetOutputPort());
        m_CurrentActor->GetProperty()->SetColor(1, 1, 1); // 白色
    } 
    else 
    {
        // 使用低API模式
        IVtkOCC_Shape::Handle aShapeImpl = new IVtkOCC_Shape(m_shape);
        IVtkVTK_ShapeData::Handle aDataImpl = new IVtkVTK_ShapeData();
        IVtk_IShapeMesher::Handle aMesher = new IVtkOCC_ShapeMesher();
        aMesher->Build(aShapeImpl, aDataImpl);
        m_CurrentMapper->SetInputData(aDataImpl->getVtkPolyData());
        m_CurrentActor->GetProperty()->SetColor(1, 1, 0); // 黄色
    }

    // 创建新Actor
    m_CurrentActor->SetMapper(m_CurrentMapper);
    m_Renderer->AddActor(m_CurrentActor);
}

vtkSmartPointer<vtkImageData> CreateButtonTexture(const char* label)
{
    vtkSmartPointer<vtkImageData> imageData = vtkSmartPointer<vtkImageData>::New();
    imageData->SetDimensions(100, 30, 1);
    imageData->AllocateScalars(VTK_UNSIGNED_CHAR, 4);
    unsigned char* pixel = static_cast<unsigned char*>(imageData->GetScalarPointer());
    memset(pixel, 0, 100 * 30 * 4); // 填充黑色背景

    // 使用vtkTextActor添加文字标签
    vtkNew<vtkTextActor> textActor;
    textActor->SetInput(label);
    textActor->GetTextProperty()->SetColor(1, 1, 1); // 白色文字
    textActor->GetTextProperty()->SetFontSize(20);
    textActor->GetTextProperty()->SetJustificationToCentered();
    textActor->SetPosition(50, 5); // 居中显示

    // 临时渲染器将文字绘制到图像
    vtkNew<vtkRenderer> tempRenderer;
    vtkNew<vtkRenderWindow> tempWindow;
    tempWindow->SetSize(100, 30);    
    //tempWindow->SetOffScreenRendering(1);
    tempWindow->AddRenderer(tempRenderer);
    tempRenderer->AddActor(textActor);
    tempRenderer->SetBackground(0, 0, 0);
    tempWindow->Render();

    // 使用vtkWindowToImageFilter捕获窗口内容
    vtkNew<vtkWindowToImageFilter> windowToImage;
    windowToImage->SetInput(tempWindow);
    windowToImage->Update();

    // 将结果拷贝到imageData
    imageData->DeepCopy(windowToImage->GetOutput());
    return imageData;
}

void VTKRenderer::CreateSwitchAPIButton()
{
    // 确保按钮组件已初始化
    if (!m_ButtonRep || !m_ButtonWidget) return;

    // 按钮位置和样式
    m_ButtonRep->SetNumberOfStates(2);    
    m_ButtonRep->SetButtonTexture(0, CreateButtonTexture("High API"));
    m_ButtonRep->SetButtonTexture(1, CreateButtonTexture("Low API"));

    m_ButtonRep->SetPlaceFactor(1);
	double bounds[6] = {10, 110, 10, 40, 0, 0};
    m_ButtonRep->PlaceWidget(bounds); // 调整按钮位置和大小

    // 按钮回调
    vtkNew<vtkCallbackCommand> buttonCallback;
    buttonCallback->SetCallback([](vtkObject* caller, unsigned long eid, void* clientdata, void* calldata)
	{
        VTKRenderer* self = static_cast<VTKRenderer*>(clientdata);
        if (!self || !self->m_RenderWindow) return;
        self->SwitchRenderAPI();
    });
    buttonCallback->SetClientData(this);

    m_ButtonWidget->SetRepresentation(m_ButtonRep);
    m_ButtonWidget->AddObserver(vtkCommand::StateChangedEvent, buttonCallback);
    m_ButtonWidget->SetInteractor(m_Interactor);
    m_ButtonWidget->On();
}

void VTKRenderer::InitialMouseEvent()
{
    vtkNew<vtkCallbackCommand> mouseMoveCallback;
    mouseMoveCallback->SetCallback([](vtkObject* caller, unsigned long eid, void* clientdata, void* calldata) 
    {
        auto self = static_cast<VTKRenderer*>(clientdata);
        auto interactor = static_cast<vtkRenderWindowInteractor*>(caller);
        int* pos = interactor->GetEventPosition();
        self->UpdateMousePosition(pos[0], pos[1]);
    });
    m_Interactor->AddObserver(vtkCommand::MouseMoveEvent, mouseMoveCallback);
    mouseMoveCallback->SetClientData(this); 
}

void VTKRenderer::UpdateMousePosition(int x, int y)
{
    string text = "Mouse: (" + to_string(x) + ", " + to_string(y) + ")";
    m_MousePositionText->SetInput(text.c_str());
    m_RenderWindow->Render();
}

void VTKRenderer::ClearHighLightState()
{
    if (m_HighlightedActor)
        m_HighlightedActor->GetProperty()->SetColor(1,1,1);

    for (auto actor : m_SelectedActors)
        actor->GetProperty()->SetColor(1,1,1);
    m_SelectedActors.clear();
}